#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> 
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>


#define OWN_IP      "192.168.231.131"       //ubuntu 本地的ip地址，作为客户端
#define OWN_PORT    5000                    //ubuntu 本地的端口号，作为客户端

#define SERVER_IP   "192.168.231.131"         //对方的ip地址，作为服务端
#define SERVER_PORT 5001                    //对方的端口号，作为服务端


/***建立客户端发送文件***/
/*
1、建立套接字
2、绑定本地IP地址和端口号
3、连接服务器
4、和服务器进行通信
5、关闭套接字
*/
int main(int argc, char* argv[])
{
    if(2 > argc)                                        //终端输入命令需要输入发送的文件路径
    {
        return -1;
    }

    int socket_fd = 0;
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);        //建立套接字
    if(-1 == socket_fd)
    {
        perror("socket error");
        return -1;
    }


    struct sockaddr_in own_addr;                        //定义一个IPv4结构体变量，初始化自己的（客户端）的ip地址、端口号
    own_addr.sin_family = AF_INET;
    own_addr.sin_addr.s_addr = inet_addr(OWN_IP);
    own_addr.sin_port = htons(OWN_PORT);

    int ret = 0;                                        //绑定自己的（客户端）的ip地址、端口号
    ret = bind(socket_fd, (struct sockaddr *)&own_addr, sizeof(struct sockaddr));
    if(-1 == ret)
    {
        perror("bind error");
        return -1;
    }

    char *own_ip = inet_ntoa(own_addr.sin_addr);        //ip地址：网络ip---->本地ip
    uint16_t own_port = ntohs(own_addr.sin_port);       //端口号：网络端口号---->本地端口号

    printf("Successfully bind to local: [%s][%d]\n", own_ip, own_port);

    struct sockaddr_in server_addr;                        //定义一个IPv4结构体变量，初始化服务端的ip地址、端口号
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
    server_addr.sin_port = htons(SERVER_PORT);

                                                            //连接服务器
    ret = connect(socket_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
    if(-1 == ret)
    {
        perror("connect error");
        return -1;
    }

    char *server_ip = inet_ntoa(server_addr.sin_addr);      //ip地址：网络ip---->本地ip
    uint16_t server_port = ntohs(server_addr.sin_port);     //端口号：网络端口号---->本地端口号

    printf("The server is successfully connected: [%s][%d]\n", server_ip, server_port);

    char buf[1024] = {0};

    ssize_t read_size = 0;
    int s_file_fd = 0;
    int path_len = 0;
    int file_size = 0;

    s_file_fd = open(argv[1], O_RDONLY);
    if(-1 == s_file_fd)
    {
        perror("open file sent by server failed");
        return -1;
    }

    memset(buf, 0, sizeof(buf));
    strcpy(buf, argv[1]);
    path_len = strlen(argv[1]) + 1;
    ret = send(socket_fd, buf, path_len, 0);         //发送文件路径
    if(ret < path_len)
    {
        perror("send file path failed");
        return -1;
    }
    ret = recv(socket_fd, buf, sizeof(buf), 0);      //接收服务端的应答
    if (-1 == ret)
    {
        perror("recv error");
        return -1;
    }
    else if(0 == ret)
    {
        printf("client disconnected.\n");
        return -1;
    }
    printf("client accepted filename successfully.\n");


    while(true)                                             //开始发送文件数据
    {
        read_size = read(s_file_fd, buf, sizeof(buf));
        if(-1 == read_size)
        {
            perror("read error");
            return -1;
        }
        else if(0 == read_size)
        {
            printf("send file data finished.\n");
            break;
        }

        ret = send(socket_fd, buf, read_size, 0);
        if(ret < read_size)
        {
            perror("send error");
            return -1;
        }

        file_size += ret;
        printf("had sent %d bytes data.\n", file_size);                      //显示发送数据的进度
    }
    
    ret = close(socket_fd);
    if(-1 == ret)
    {
        perror("close error");
        return -1;
    }

    return 0;
}